#pragma once

#include "stdafx.h"

namespace natrium {
	namespace video {
		/*
		 * Shader Program wrapper
		 */

		enum eShaderType {
			VERTEX = GL_VERTEX_SHADER,
			FRAGMENT = GL_FRAGMENT_SHADER,
			GEOMETRY = GL_GEOMETRY_SHADER,
			TESS_CONTROL = GL_TESS_CONTROL_SHADER,
			TESS_EVAL = GL_TESS_EVALUATION_SHADER,
			COMPUTE = GL_COMPUTE_SHADER
		};

		class Program {
		public:
			Program();
			~Program();

			bool compile(const std::string& source, eShaderType type);
			bool compileFile(const std::string& filename, eShaderType type);
			bool link();
			void use();

			bool isLinked() const;

			void bindAttribLocation(GLuint location, const std::string& name);
			void bindFragDataLocation(GLuint location, const std::string& name);

			//setting Uniform values
			void set(const std::string& name, float x, float y, float z);
			void set(const std::string& name, float x, float y, float z, float w);
			void set(const std::string& name, const glm::vec3& v);
			void set(const std::string& name, const glm::vec4& v);
			void set(const std::string& name, const glm::mat3& m);
			void set(const std::string& name, const glm::mat4& m);
			void set(const std::string& name, float value);
			void set(const std::string& name, int value);
			void set(const std::string& name, bool value);

			void listActiveUniforms() const;
			void listActiveAttribs() const;

			GLuint getHandle() const;

		private:
			GLint getUniformLocation(const std::string& name); //fails silently (returns 0 upon failure)

			GLuint mHandle;
			bool mLinked;
			std::vector<GLuint> mAttachedShaders;
		};
	}
}